﻿using System;
using System.Collections;
using System.Collections.Generic;
using Pfz.DynamicObjects;

namespace Pfz.Collections
{
	/// <summary>
	/// Class responsible of creating read-only wrappers over normal dictionaries.
	/// </summary>
	public static class ReadOnlyDictionary<TKey, TValue>
	{
		private static readonly Func<IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>> _creator;

		/// <summary>
		/// Initializes the dynamic module.
		/// </summary>
		static ReadOnlyDictionary()
		{
			var adapterGenerator = new AdapterGenerator();
			adapterGenerator.AllowMissingMethods = true;

			var collectionConversion = adapterGenerator.GetCreator<ICollection<TKey>, ICollection>();
			adapterGenerator.Conversions.Register(collectionConversion);

			if (typeof(TKey) != typeof(TValue))
			{
				var collectionConversion2 = adapterGenerator.GetCreator<ICollection<TValue>, ICollection>();
				adapterGenerator.Conversions.Register(collectionConversion2);
			}

			if (typeof(TValue).IsValueType)
			{
				adapterGenerator.Conversions.Register<TValue, object>((value) => value);
				adapterGenerator.Conversions.Register<object, TValue>((value) => (TValue)value);
			}
			
			_creator = adapterGenerator.GetCreator<IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>>();
		}

		/// <summary>
		/// Creates a read-only wrapper over a normal (modifiable) dictionary.
		/// </summary>
		public static IReadOnlyDictionary<TKey, TValue> Create(IDictionary<TKey, TValue> modifiableDictionary)
		{
			if (modifiableDictionary == null)
				throw new ArgumentNullException("modifiableDictionary");

			return _creator(modifiableDictionary);
		}
	}
}
